﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Discovery;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Crm.Sdk.Messages;
using System.Xml;
using System.IO;

namespace RoleBasedView
{
    public class View : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
           

            var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

            var service = serviceFactory.CreateOrganizationService(context.UserId);            
            
            if (context.InputParameters.Contains("Query") && context.InputParameters["Query"] is QueryExpression && context.Stage == 40)
            {
                
                var qe = (QueryExpression)context.InputParameters["Query"];

                //try
                //{               

                    if (qe.Criteria != null)
                    {
                        var condition = (ConditionExpression)qe.Criteria.Conditions[1];
                        int typeCode = Convert.ToInt32(condition.Values[0].ToString());
                        
                        Entity objRoleBasedViewentity = GetRecordsFromRoleBasedView(typeCode, service);

                        if (objRoleBasedViewentity != null)
                        {
                            // Get all the view name from the View List entity
                            GetRoleFromRoleEntity(context.InitiatingUserId, service, objRoleBasedViewentity, context);
                        }                       

                    }
                //}
                //catch (Exception ex)
                //{
                //    //throw new InvalidPluginExecutionException("Function Execute : " + ex.ToString());
                //}
            }
        }

        private Dictionary<string, string> GetViewList(Guid entityId, IOrganizationService service)
        {
            
            string roleid = string.Empty;
            string viewName = string.Empty;
            Dictionary<string, string> viewList = new Dictionary<string, string>();

            EntityCollection entity = null;
            //try
            //{
                QueryExpression query = new QueryExpression
                {
                    EntityName = "new_rolesviewlist",
                    ColumnSet = new ColumnSet(true),
                    Criteria = new FilterExpression
                    {
                        Filters =
                          {
                            new FilterExpression
                            {
                              Conditions =
                              {
                                new ConditionExpression("new_rolebasedview_linked", ConditionOperator.Equal, entityId)
                              }
                            }
                         }
                    }
                };

                DataCollection<Entity> listOfView = service.RetrieveMultiple(query).Entities;
                string rolename = string.Empty;
                string tmpViewName = string.Empty;
                foreach (Entity view in listOfView)
                {
                    
                    //roleid = view.GetAttributeValue<EntityReference>("new_role").Id.ToString();
                    roleid = view.GetAttributeValue<EntityReference>("new_role").Name.ToString();
                    rolename += roleid + " | ";
                    foreach (Entity views in listOfView)
                    {
                        if ((roleid == views.GetAttributeValue<EntityReference>("new_role").Name.ToString()) && (!viewList.ContainsKey(roleid)))
                        {
                            viewName += views["new_viewname"].ToString() + "|"; 
                        }                                          
                    }

                    if (!viewList.ContainsKey(roleid))
                    {
                        viewList.Add(roleid, viewName);
                        tmpViewName = viewName;
                        viewName = string.Empty;                        
                    }

                }

                //throw new InvalidPluginExecutionException("Function GetViewList : " + tmpViewName);


            //}
            //catch (Exception ex)
            //{
            //    //throw new InvalidPluginExecutionException("Function GetViewList : " + ex.ToString());
            //}
           
            return viewList;
        }

        private EntityCollection ChangeViewCollection(string ourDefaultViewName, EntityCollection records)
        {
            EntityCollection objViewCollection = new EntityCollection() ;
            string[] splitDefaultViewName = ourDefaultViewName.Split('|');
            //try
            //{
                foreach (string view in splitDefaultViewName)
                {
                    foreach (Entity record in records.Entities)
                    {
                        if (record.Contains("name"))
                        {
                            string viewName = (string)record["name"];
                            if (viewName.Equals(view.Trim()))
                            {
                                if (!objViewCollection.Entities.Contains(record))
                                {
                                    objViewCollection.Entities.Add(record);
                                }
                            }                            
                        }
                    }
                }
            //}
            //catch (Exception ex)
            //{
            //    //throw new InvalidPluginExecutionException("Function ChangeViewCollection : " + ex.ToString());
            //}
            return objViewCollection;
        }

        private Entity GetRecordsFromRoleBasedView(int typecode, IOrganizationService service)
        {
            Entity entity = null;
            //try
            //{
                QueryExpression query = new QueryExpression
                {
                    EntityName = "rbv_rolebasedview",
                    ColumnSet = new ColumnSet(true),
                    Criteria = new FilterExpression
                    {
                        Filters =
                          {
                            new FilterExpression
                            {
                              Conditions =
                              {
                                new ConditionExpression("rbv_entitytypecode", ConditionOperator.Equal, typecode)
                              }
                            }
                         }
                    }
                };
                entity = service.RetrieveMultiple(query).Entities.FirstOrDefault();
                if (entity != null)
                    return entity;
            //}
            //catch (Exception ex)
            //{
            //    //throw new InvalidPluginExecutionException("Function GetRecordsFromRoleBasedView : " + ex.ToString());
            //}
            return entity;
        }

        private void GetRoleFromRoleEntity(Guid userid, IOrganizationService service, Entity roleBasedViewEntity,IPluginExecutionContext context)
        {
            Dictionary<string, string> listOfView = GetViewList(roleBasedViewEntity.Id, service);                
                 
            QueryExpression userRolesQuery = new QueryExpression()
            {

                LinkEntities =
                { 

                    new LinkEntity
                    {
                        LinkFromEntityName = "role",
                        LinkFromAttributeName = "roleid",
                        LinkToEntityName = "systemuserroles",
                        LinkToAttributeName = "roleid",
                        LinkCriteria = new FilterExpression
                        {
                            FilterOperator = LogicalOperator.And,
                            Conditions =
                            {
                                new ConditionExpression
                                {
                                    AttributeName = "systemuserid",
                                    Operator = ConditionOperator.Equal,
                                    Values = { userid}
                                }
                            }
                         }
                    }

                }

            };



            userRolesQuery.ColumnSet = new ColumnSet(true);
            userRolesQuery.EntityName = "role";

            

            // Obtain results from the query expression.
            var userRoles = service.RetrieveMultiple(userRolesQuery);
            string nameOfViewList = string.Empty;
            
            for (int i = 0; i < userRoles.Entities.Count; i++)
            {
                //if (listOfView.ContainsKey(userRoles.Entities[i].Attributes["roleid"].ToString()))
                if (listOfView.ContainsKey(userRoles.Entities[i].Attributes["name"].ToString()))
                {
                    nameOfViewList += listOfView[userRoles.Entities[i].Attributes["name"].ToString()];                    
                }                           
            }

            if (!string.IsNullOrEmpty(nameOfViewList))
            {
                var collection = (EntityCollection)context.OutputParameters["BusinessEntityCollection"];
                collection = ChangeViewCollection(nameOfViewList, collection);
                context.OutputParameters["BusinessEntityCollection"] = collection;
            }
           
            
        }
    }
}
